home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / Framework / Sources / UUndo.cp < prev    next >
Encoding:
Text File  |  1996-04-03  |  30.9 KB  |  1,094 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UUndo.cp 
  3. // Copyright © 1996 by Apple Computer, Inc. All rights reserved.
  4. //----------------------------------------------------------------------------------------
  5.  
  6. #ifndef __UUNDO__
  7. #include "UUndo.h"
  8. #endif
  9.  
  10. // MacApp
  11.  
  12. #ifndef __UAPPLEEVENTS__
  13. #include "UAppleEvents.h"
  14. #endif
  15.  
  16. #ifndef __UDISPATCHER__
  17. #include "UDispatcher.h"
  18. #endif
  19.  
  20. #ifndef __UFAILURE__
  21. #include "UFailure.h"
  22. #endif
  23.  
  24. #ifndef __UMACAPPGLOBALS__
  25. #include "UMacAppGlobals.h"
  26. #endif
  27.  
  28. #ifndef __UMACAPPUTILITIES__
  29. #include "UMacAppUtilities.h"
  30. #endif
  31.  
  32. #ifndef __UMENUMGR__
  33. #include "UMenuMgr.h"
  34. #endif
  35.  
  36. // Toolbox
  37.  
  38. #ifndef __AEREGISTRY__
  39. #include <AERegistry.h>
  40. #endif
  41.  
  42. // ANSI
  43.  
  44. #ifndef __STDIO__
  45. #include <stdio.h>
  46. #endif
  47.  
  48. //========================================================================================
  49. // GLOBAL Variables
  50. //========================================================================================
  51.  
  52. TUndoHandler*        TUndoHandler::fgUndoHandler;
  53.  
  54. const ArrayIndex    TActionStack::sMaxDesiredItems = 25;    // Maximum number of entried in stack.
  55.  
  56. //========================================================================================
  57. // GLOBAL Procedures
  58. //========================================================================================
  59. #undef Inherited
  60.  
  61. //----------------------------------------------------------------------------------------
  62. // GetUndoText: 
  63. //----------------------------------------------------------------------------------------
  64. #pragma segment MAApplicationRes
  65.  
  66. void GetUndoRedoText(Boolean cmdDone, CommandNumber aCommandNumber, CStr255& undoName)
  67. {
  68.     short newMenuState;
  69.  
  70.     if (aCommandNumber == cCantUndo)
  71.         newMenuState = bzCantUndo;
  72.     else if (cmdDone)
  73.         newMenuState = bzUndo;
  74.     else
  75.         newMenuState = bzRedo;
  76.  
  77.     GetIndString(undoName, kIDBuzzString, newMenuState);
  78.  
  79.     short preCmdName;
  80.     short constChars;
  81.     if (ParseTitleTemplate(undoName, preCmdName, constChars))
  82.     {
  83.         CStr255 cmdName;
  84.         if ((aCommandNumber != cNoCommand) && (aCommandNumber != cCantUndo))
  85.             CommandToName(aCommandNumber, cmdName);
  86.         SubstituteInTitle(undoName, cmdName, preCmdName, constChars);
  87.     }
  88. }
  89.  
  90. //========================================================================================
  91. // CLASS TUndoAction
  92. //========================================================================================
  93. #undef Inherited
  94. #define Inherited TObject
  95.  
  96. #pragma segment MAConstructorRes
  97. MA_DEFINE_CLASS_M1(TUndoAction, Inherited);
  98.  
  99. //----------------------------------------------------------------------------------------
  100. // NewUndoHandler
  101. //----------------------------------------------------------------------------------------
  102. #pragma segment MAInit
  103.  
  104. TUndoAction* TUndoAction::NewUndoAction(TCommand* command, EActionType actionType, CommandNumber id)
  105. {
  106.     MAVolatileInit(TUndoAction*, it, new TUndoAction);
  107.     FailInfo fi;
  108.     Try(fi)
  109.     {
  110.         it->IUndoAction(command, actionType, id);
  111.         fi.Success();
  112.     }
  113.     else // Recover
  114.     {
  115.         it = (TUndoAction*) FreeIfObject(it);
  116.         fi.ReSignal();
  117.     }
  118.     return it;
  119. }
  120.  
  121. //----------------------------------------------------------------------------------------
  122. // TUndoAction constructor
  123. //----------------------------------------------------------------------------------------
  124. #pragma segment MAInit
  125.  
  126. TUndoAction::TUndoAction() :
  127.     fCommand(NULL),
  128.     fActionType(kSingleAction),
  129.     fMark(FALSE)
  130. {
  131. }
  132.  
  133. //----------------------------------------------------------------------------------------
  134. // TUndoAction destructor
  135. //----------------------------------------------------------------------------------------
  136. #pragma segment MATerminate
  137.  
  138. TUndoAction::~TUndoAction()
  139. {
  140.     fCommand = (TCommand*) FreeIfObject(fCommand);
  141. }
  142.  
  143. //----------------------------------------------------------------------------------------
  144. // TUndoAction::IUndoAction:
  145. //----------------------------------------------------------------------------------------
  146. #pragma segment MAInit
  147.  
  148. void TUndoAction::IUndoAction(TCommand* command, EActionType actionType, CommandNumber id)
  149. {
  150.     IObject();
  151.     
  152.     fCommand = command;
  153.     fID = id;
  154.     fActionType = actionType;
  155.     fMark = FALSE;
  156. }
  157.  
  158. //----------------------------------------------------------------------------------------
  159. // TUndoAction::IsDone:
  160. //----------------------------------------------------------------------------------------
  161. #pragma segment MAInit
  162.  
  163. Boolean TUndoAction::IsDone()
  164. {
  165.     return fCommand ? fCommand->fCommandDone : FALSE;
  166. }
  167.  
  168. //========================================================================================
  169. // CLASS TActionStack
  170. //========================================================================================
  171. #undef Inherited
  172. #define Inherited TObject
  173.  
  174. #pragma segment MAConstructorRes
  175. MA_DEFINE_CLASS_M1(TActionStack, Inherited);
  176.  
  177. //----------------------------------------------------------------------------------------
  178. // NewUndoHandler
  179. //----------------------------------------------------------------------------------------
  180. #pragma segment MAInit
  181.  
  182. TActionStack* TActionStack::NewActionStack()
  183. {
  184.     MAVolatileInit(TActionStack*, it, new TActionStack);
  185.     FailInfo fi;
  186.     Try(fi)
  187.     {
  188.         it->IActionStack();
  189.         fi.Success();
  190.     }
  191.     else // Recover
  192.     {
  193.         it = (TActionStack*) FreeIfObject(it);
  194.         fi.ReSignal();
  195.     }
  196.     return it;
  197. }
  198.  
  199. //----------------------------------------------------------------------------------------
  200. // TActionStack constructor
  201. //----------------------------------------------------------------------------------------
  202. #pragma segment MAInit
  203.  
  204. TActionStack::TActionStack()
  205. {
  206. }
  207.  
  208. //----------------------------------------------------------------------------------------
  209. // TActionStack destructor
  210. //----------------------------------------------------------------------------------------
  211. #pragma segment MATerminate
  212.  
  213. TActionStack::~TActionStack()
  214. {
  215. }
  216.  
  217. //----------------------------------------------------------------------------------------
  218. // TActionStack::IActionStack:
  219. //----------------------------------------------------------------------------------------
  220. #pragma segment MAInit
  221.  
  222. void TActionStack::IActionStack()
  223. {
  224.     IList();
  225.  
  226. #if qDebug
  227.     SetEltType(&TUndoAction::fgClassDesc);
  228. #endif
  229. }
  230.  
  231. //----------------------------------------------------------------------------------------
  232. // TActionStack::PushAction:
  233. //----------------------------------------------------------------------------------------
  234. #pragma segment MASelCommand
  235.  
  236. void TActionStack::PushAction(TUndoAction* action)
  237. {
  238.     Push(action);
  239.     
  240.     // Purge some actions if we've busted through the max desired.
  241.     if (fSize > sMaxDesiredItems)
  242.         Purge(kMaxLong, sMaxDesiredItems);
  243. }
  244.  
  245. //----------------------------------------------------------------------------------------
  246. // TActionStack::ClearActionsToMark:
  247. //----------------------------------------------------------------------------------------
  248. #pragma segment MASelCommand
  249.  
  250. void TActionStack::ClearActionsToMark()
  251. {
  252.     TUndoAction* action;
  253.     while ((action = Top()) != NULL && !action->fMark)
  254.     {
  255.         action = PopAction();
  256.         action = (TUndoAction*) FreeIfObject(action);
  257.     }
  258. }
  259.  
  260. //----------------------------------------------------------------------------------------
  261. // TActionStack::FindTransaction:
  262. //----------------------------------------------------------------------------------------
  263. #pragma segment MASelCommand
  264.  
  265. TUndoAction* TActionStack::FindTransaction(TCommand* command, Boolean itsForward)
  266. {
  267.     TUndoAction* transaction = NULL;
  268.     long level = 0;
  269.     Boolean found = FALSE;
  270.     
  271.     CObjectIterator iter(this, itsForward);
  272.     for (TUndoAction* action = (TUndoAction*) iter.FirstObject(); iter.More(); action = (TUndoAction*) iter.NextObject())
  273.     {
  274.         EActionType actionType = action->fActionType;
  275.         if (level == 0)
  276.         {
  277.             if ((actionType == kSingleAction) || (actionType == kBeginAction))
  278.                 transaction = action;
  279.         }
  280.         
  281.         if (actionType == kBeginAction)
  282.             ++level;
  283.         else if (actionType == kEndAction)
  284.             --level;
  285.  
  286.         if (action->fCommand == command)
  287.         {
  288.             found = TRUE;
  289.             break;
  290.         }
  291.     }
  292.     
  293.     return found ? transaction : NULL;
  294. }
  295.  
  296. //----------------------------------------------------------------------------------------
  297. // TActionStack::Purge:
  298. //----------------------------------------------------------------------------------------
  299. #pragma segment MAMemoryRes
  300. Size TActionStack::Purge(Size needed, ArrayIndex numToLeave)
  301. {
  302.     // NOTE: This function does not currently support the 'needed' parameter.
  303.     // Unload possibly even the topmost entry in the stack.
  304.     Size    freed = 0;
  305.  
  306.     // Locate the topmost action to which we will unload.
  307.     ArrayIndex        i = 0;
  308.     ArrayIndex        j = 0;
  309.     ArrayIndex        limit = fSize - numToLeave;
  310.     
  311.     while (i <= limit && freed < needed)
  312.     {
  313.         i++;
  314.         TUndoAction*    action = (TUndoAction*)At(i);
  315.         Size            freeableSize = 0; // Was: action->Size();
  316.         
  317.         EActionType actionType = action->fActionType;
  318.         if (actionType == kBeginAction)
  319.         {
  320.             // Skip over this transaction.
  321.             long transaction = 1;
  322.             do
  323.             {
  324.                 i++;
  325.                 action = (TUndoAction*)At(i);
  326.                 //freeableSize += action->Size();
  327.                 
  328.                 actionType = action->fActionType;
  329.                 if (actionType == kBeginAction)
  330.                     ++transaction;
  331.                 else if (actionType == kEndAction)
  332.                     --transaction;
  333.             } while (i <= limit && transaction != 0);
  334.         }
  335.         if (i <= limit)
  336.         {
  337.             j = i;
  338.             freed += freeableSize;
  339.         }
  340.     }
  341.     
  342.     for (i = 1; i <= j; i++)
  343.     {
  344.         TUndoAction*    action = (TUndoAction*)At(i);
  345.         FreeIfObject(action);
  346.     }
  347.     
  348.     // Now flush the targetted entries from the list.
  349.     DeleteElementsAt(1, j);
  350.     
  351.     return freed;
  352. }
  353.  
  354. //========================================================================================
  355. // CLASS TUndoHandler
  356. //========================================================================================
  357. #undef Inherited
  358. #define Inherited TObject
  359.  
  360. #pragma segment MAConstructorRes
  361. MA_DEFINE_CLASS_M1(TUndoHandler, Inherited);
  362.  
  363. //----------------------------------------------------------------------------------------
  364. // InitUUndoHandler
  365. //----------------------------------------------------------------------------------------
  366. #pragma segment MAInit
  367.  
  368. void TUndoHandler::InitUUndo()
  369. {
  370.     fgUndoHandler = NewUndoHandler();
  371. }
  372.  
  373. //----------------------------------------------------------------------------------------
  374. // NewUndoHandler
  375. //----------------------------------------------------------------------------------------
  376. #pragma segment MAInit
  377.  
  378. TUndoHandler* TUndoHandler::NewUndoHandler()
  379. {
  380.     MAVolatileInit(TUndoHandler*, it, new TUndoHandler);
  381.     FailInfo fi;
  382.     Try(fi)
  383.     {
  384.         it->IUndoHandler();
  385.         fi.Success();
  386.     }
  387.     else // Recover
  388.     {
  389.         it = (TUndoHandler*) FreeIfObject(it);
  390.         fi.ReSignal();
  391.     }
  392.     return it;
  393. }
  394.  
  395. //----------------------------------------------------------------------------------------
  396. // TUndoHandler constructor
  397. //----------------------------------------------------------------------------------------
  398. #pragma segment MAInit
  399.  
  400. TUndoHandler::TUndoHandler() :
  401.     fUndoStack(NULL),
  402.     fRedoStack(NULL),
  403.     fInTransaction(0)
  404. {
  405. }
  406.  
  407. //----------------------------------------------------------------------------------------
  408. // TUndoHandler destructor
  409. //----------------------------------------------------------------------------------------
  410. #pragma segment MATerminate
  411.  
  412. TUndoHandler::~TUndoHandler()
  413. {
  414.     fUndoStack = (TActionStack*) FreeListIfObject(fUndoStack);
  415.     fRedoStack = (TActionStack*) FreeListIfObject(fRedoStack);
  416. }
  417.  
  418. //----------------------------------------------------------------------------------------
  419. // TUndoHandler::IUndoHandler:
  420. //----------------------------------------------------------------------------------------
  421. #pragma segment MAInit
  422.  
  423. void TUndoHandler::IUndoHandler()
  424. {
  425.     IObject();
  426.     
  427.     fUndoStack = TActionStack::NewActionStack();
  428.     fRedoStack = TActionStack::NewActionStack();
  429. }
  430.  
  431. //----------------------------------------------------------------------------------------
  432. // TUndoHandler::AddActionToHistory:
  433. //----------------------------------------------------------------------------------------
  434. #pragma segment MASelCommand
  435.  
  436. void TUndoHandler::AddActionToHistory(TCommand* command, EActionType actionType, CommandNumber id)
  437. {
  438.     Boolean shortCut = FALSE;
  439.     if ((fInTransaction > 0) && (actionType == kSingleAction))
  440.     {
  441.         TUndoAction* action = fUndoStack->Top();
  442.         if (action && (action->fActionType == kBeginAction) && (action->fCommand == NULL))
  443.         {
  444.             // Stuff the command in the begin action, instead of allocating
  445.             // a new single action
  446.             action->fCommand = command;
  447.             action->fID = id;
  448.             shortCut = TRUE;
  449.         }
  450.     }
  451.     
  452.     if (!shortCut)
  453.     {
  454.         if (actionType == kBeginAction)
  455.             ++fInTransaction;
  456.         else if (actionType == kEndAction)
  457.             --fInTransaction;
  458.  
  459.         fUndoStack->PushAction(TUndoAction::NewUndoAction(command, actionType, id));
  460.     }
  461.     
  462.     ClearRedoHistory();
  463. }
  464.  
  465. //----------------------------------------------------------------------------------------
  466. // TUndoHandler::BeginAction:
  467. //----------------------------------------------------------------------------------------
  468. #pragma segment MASelCommand
  469.  
  470. void TUndoHandler::BeginAction()
  471. {
  472.     AddActionToHistory(NULL, kBeginAction, cNoCommand);
  473. }
  474.  
  475. //----------------------------------------------------------------------------------------
  476. // TUndoHandler::EndAction:
  477. //----------------------------------------------------------------------------------------
  478. #pragma segment MASelCommand
  479.  
  480. void TUndoHandler::EndAction()
  481. {
  482.     Boolean shortCut = TRUE;
  483.     CommandNumber id = cNoCommand;
  484.     TUndoAction* action = fUndoStack->Top();
  485.     if (action)
  486.     {
  487.         if (action->fActionType == kBeginAction)
  488.         {
  489.             if (action->fCommand == NULL)
  490.             {
  491.                 // Transaction is empty -- remove it
  492.                 fUndoStack->PopAction();
  493.             }
  494.             else
  495.             {
  496.                 // Convert to a single action and we don't have to add an end
  497.                 action->fActionType = kSingleAction;
  498.             }
  499.         }
  500.         else if ((action->fActionType == kSingleAction))
  501.         {
  502.             // Convert last single action to an end instead of adding one
  503.             action->fActionType = kEndAction;
  504.         }
  505.         else
  506.         {
  507.             // Get the id of the last single action, so the end action
  508.             // will have the same id (for the undo and redo menus)
  509.             id = action->fID;
  510.             shortCut = FALSE;
  511.         }
  512.     }
  513.     
  514.     if (shortCut)
  515.         --fInTransaction;
  516.     else
  517.         AddActionToHistory(NULL, kEndAction, id);
  518. }
  519.  
  520. //----------------------------------------------------------------------------------------
  521. // TUndoHandler::AbortCurrentTransaction:
  522. //----------------------------------------------------------------------------------------
  523. #pragma segment MASelCommand
  524.  
  525. void TUndoHandler::AbortCurrentTransaction()
  526. {
  527.     if (fInTransaction > 0)
  528.     {
  529.         long nextTransaction = fInTransaction - 1;
  530.         TUndoAction* action;
  531.         while ((action = fUndoStack->PopAction()) != NULL)
  532.         {
  533.             EActionType actionType = action->fActionType;
  534.             action = (TUndoAction*) FreeIfObject(action);
  535.             
  536.             if (actionType == kEndAction)
  537.                 ++fInTransaction;
  538.             else if (actionType == kBeginAction)
  539.             {
  540.                 if (--fInTransaction <= nextTransaction)
  541.                     break;
  542.             }
  543.         }
  544.         
  545. #if qDebug
  546.         Assertion(fInTransaction == nextTransaction,
  547.                   "\pEnd of undo stack before end of transaction");
  548. #endif
  549.     }
  550. }
  551.  
  552. //----------------------------------------------------------------------------------------
  553. // TUndoHandler::ClearActionHistory:
  554. //----------------------------------------------------------------------------------------
  555. #pragma segment MASelCommand
  556.  
  557. void TUndoHandler::ClearActionHistory(ERespectMarksChoices respectMarks)
  558. {
  559.     if (respectMarks == kDontRespectMarks)
  560.     {
  561.         fUndoStack->FreeAll();
  562.         fRedoStack->FreeAll();
  563.     }
  564.     else
  565.     {
  566.         fUndoStack->ClearActionsToMark();
  567.         fRedoStack->ClearActionsToMark();
  568.     }
  569. }
  570.  
  571. //----------------------------------------------------------------------------------------
  572. // TUndoHandler::MarkActionHistory:
  573. //----------------------------------------------------------------------------------------
  574. #pragma segment MASelCommand
  575.  
  576. void TUndoHandler::MarkActionHistory()
  577. {
  578.     TUndoAction* action = fUndoStack->Top();
  579.     if (action)
  580.         action->fMark = TRUE;
  581.     
  582.     action = fRedoStack->Top();
  583.     if (action)
  584.         action->fMark = TRUE;
  585. }
  586.  
  587. //----------------------------------------------------------------------------------------
  588. // TUndoHandler::FindTransaction:
  589. //----------------------------------------------------------------------------------------
  590. #pragma segment MASelCommand
  591.  
  592. TUndoAction* TUndoHandler::FindTransaction(TCommand* command)
  593. {
  594.     TUndoAction* action = fUndoStack->FindTransaction(command, kIterateForward);
  595.     if (!action)
  596.         action = fRedoStack->FindTransaction(command, kIterateBackward);
  597.     
  598.     return action;
  599. }
  600.  
  601. //----------------------------------------------------------------------------------------
  602. // TUndoHandler::Abort:
  603. //----------------------------------------------------------------------------------------
  604. #pragma segment MASelCommand
  605.  
  606. void TUndoHandler::Abort()
  607. {
  608.     long transaction = fInTransaction;
  609.         // start with fInTransaction so we can abort a partial transaction
  610.     
  611.     do
  612.     {
  613.         EActionType actionType = AbortAction();
  614.         if (actionType == kEndAction)
  615.             ++transaction;
  616.         else if (actionType == kBeginAction)
  617.         {
  618.             --transaction;
  619. #if qDebug
  620.             Assertion(transaction >= 0, "Bad undo stack");
  621. #endif
  622.         }
  623.     }
  624.     while (transaction != 0);
  625. }
  626.  
  627. //----------------------------------------------------------------------------------------
  628. // TUndoHandler::Purge:
  629. //----------------------------------------------------------------------------------------
  630. #pragma segment MAMemoryRes
  631. Size TUndoHandler::Purge(Size needed)
  632. {
  633.     // Unload as much of the undo and redo stack as needed.
  634.     Size        totalPurged = fUndoStack->PurgeFirstPhase(kMaxLong);
  635.     if (totalPurged < needed)
  636.     {
  637.         totalPurged = fRedoStack->PurgeFirstPhase(kMaxLong);
  638.         if (totalPurged < needed)
  639.         {
  640.             totalPurged = fUndoStack->Purge(kMaxLong);
  641.             if (totalPurged < needed)
  642.                 totalPurged = fRedoStack->Purge(kMaxLong);
  643.         }
  644.     }
  645.     return totalPurged;
  646. }
  647.  
  648. //----------------------------------------------------------------------------------------
  649. // TUndoHandler::Undo:
  650. //----------------------------------------------------------------------------------------
  651. #pragma segment MASelCommand
  652.  
  653. void TUndoHandler::Undo()
  654. {
  655. #if qDebug
  656.     Assertion(fInTransaction == 0, "Undo during transaction");
  657. #endif
  658.     long transaction = 0;
  659.     do
  660.     {
  661.         EActionType actionType = UndoAction();
  662.         if (actionType == kEndAction)
  663.             ++transaction;
  664.         else if (actionType == kBeginAction)
  665.         {
  666.             --transaction;
  667. #if qDebug
  668.             Assertion(transaction >= 0, "Bad undo stack");
  669. #endif
  670.         }
  671.     }
  672.     while (transaction != 0);
  673. }
  674.  
  675. //----------------------------------------------------------------------------------------
  676. // TUndoHandler::AnythingToUndo:
  677. //----------------------------------------------------------------------------------------
  678. #pragma segment MASelCommand
  679.  
  680. Boolean TUndoHandler::AnythingToUndo()
  681. {
  682.     return (fUndoStack->fSize > 0);
  683. }
  684.  
  685. //----------------------------------------------------------------------------------------
  686. // TUndoHandler::GetUndoID:
  687. //----------------------------------------------------------------------------------------
  688. #pragma segment MASelCommand
  689.  
  690. CommandNumber TUndoHandler::GetUndoID()
  691. {
  692.     TUndoAction* action = fUndoStack->Top();
  693.     return action ? action->fID : cNoCommand;
  694. }
  695.  
  696. //----------------------------------------------------------------------------------------
  697. // TUndoHandler::GetUndoText:
  698. //----------------------------------------------------------------------------------------
  699. #pragma segment MASelCommand
  700.  
  701. void TUndoHandler::GetUndoText(CStr255& undoName)
  702. {
  703.     TUndoAction* action = fUndoStack->Top();
  704.     CommandNumber id = action ? action->fID : cNoCommand;
  705.     GetUndoRedoText(kShowUndo, id, undoName);
  706. }
  707.  
  708. //----------------------------------------------------------------------------------------
  709. // TUndoHandler::Redo:
  710. //----------------------------------------------------------------------------------------
  711. #pragma segment MASelCommand
  712.  
  713. void TUndoHandler::Redo()
  714. {
  715. #if qDebug
  716.     Assertion(fInTransaction == 0, "Redo during transaction");
  717. #endif
  718.     long transaction = 0;
  719.     do
  720.     {
  721.         EActionType actionType = RedoAction();
  722.         if (actionType == kBeginAction)
  723.             ++transaction;
  724.         else if (actionType == kEndAction)
  725.         {
  726.             --transaction;
  727. #if qDebug
  728.             Assertion(transaction >= 0, "Bad redo stack");
  729. #endif
  730.         }
  731.     }
  732.     while (transaction != 0);
  733. }
  734.  
  735. //----------------------------------------------------------------------------------------
  736. // TUndoHandler::ClearRedoHistory:
  737. //----------------------------------------------------------------------------------------
  738. #pragma segment MASelCommand
  739.  
  740. void TUndoHandler::ClearRedoHistory()
  741. {
  742.     fRedoStack->FreeAll();
  743. }
  744.  
  745. //----------------------------------------------------------------------------------------
  746. // TUndoHandler::AnythingToRedo:
  747. //----------------------------------------------------------------------------------------
  748. #pragma segment MASelCommand
  749.  
  750. Boolean TUndoHandler::AnythingToRedo()
  751. {
  752.     return (fRedoStack->fSize > 0);
  753. }
  754.  
  755. //----------------------------------------------------------------------------------------
  756. // TUndoHandler::GetRedoID:
  757. //----------------------------------------------------------------------------------------
  758. #pragma segment MASelCommand
  759.  
  760. CommandNumber TUndoHandler::GetRedoID()
  761. {
  762.     TUndoAction* action = fRedoStack->Top();
  763.     return action ? action->fID : cNoCommand;
  764. }
  765.  
  766. //----------------------------------------------------------------------------------------
  767. // TUndoHandler::GetRedoText:
  768. //----------------------------------------------------------------------------------------
  769. #pragma segment MASelCommand
  770.  
  771. void TUndoHandler::GetRedoText(CStr255& undoName)
  772. {
  773.     TUndoAction* action = fRedoStack->Top();
  774.     CommandNumber id = action ? action->fID : cNoCommand;
  775.     GetUndoRedoText(kShowRedo, id, undoName);
  776. }
  777.  
  778. //----------------------------------------------------------------------------------------
  779. // For internal use only
  780. //----------------------------------------------------------------------------------------
  781.  
  782. //----------------------------------------------------------------------------------------
  783. // TUndoHandler::AbortAction:
  784. //----------------------------------------------------------------------------------------
  785. #pragma segment MASelCommand
  786.  
  787. EActionType TUndoHandler::AbortAction()
  788. {
  789.     TUndoAction* action = fUndoStack->PopAction();
  790.     FailNonObject(action);
  791.  
  792.     EActionType actionType = action->fActionType;
  793.  
  794.     TCommand* command = action->fCommand;
  795.     if (command && command->fCommandDone && command->CanBeUndone() &&
  796.         (command->fValidationError == noErr))
  797.         AbortCommand(command);
  798.  
  799.     return actionType;
  800. }
  801.  
  802. //----------------------------------------------------------------------------------------
  803. // TUndoHandler::AbortCommand:
  804. //----------------------------------------------------------------------------------------
  805. #pragma segment MASelCommand
  806.  
  807. void TUndoHandler::AbortCommand(TCommand* command)
  808. {
  809.     FailInfo fi;
  810.     Try(fi)
  811.     {
  812.         command->Abort();
  813.         //command->FinishUndoRedo();
  814.         fi.Success();
  815.     }
  816.     else // Recover
  817.     {
  818.         command->SetValidationError(fi.error);
  819.         short aCommandNumber = (short)command->fIdentifier;
  820.         //command = CommitACommand(command);
  821.  
  822.         FailNewMessage(fi.error, fi.message, BuildMessage(aCommandNumber, messageCommandError));
  823.     }
  824. }
  825.  
  826. //----------------------------------------------------------------------------------------
  827. // TUndoHandler::UndoAction:
  828. //----------------------------------------------------------------------------------------
  829. #pragma segment MASelCommand
  830.  
  831. EActionType TUndoHandler::UndoAction()
  832. {
  833.     TUndoAction* action = fUndoStack->Top();
  834.     FailNonObject(action);
  835.  
  836.     EActionType actionType = action->fActionType;
  837.  
  838.     TCommand* command = action->fCommand;
  839.     if (command && command->fCommandDone && command->CanBeUndone() &&
  840.         (command->fValidationError == noErr))
  841.         UndoCommand(command);
  842.  
  843.     fRedoStack->PushAction(fUndoStack->PopAction());
  844.     
  845.     return actionType;
  846. }
  847.  
  848. //----------------------------------------------------------------------------------------
  849. // TUndoHandler::UndoCommand:
  850. //----------------------------------------------------------------------------------------
  851. #pragma segment MASelCommand
  852.  
  853. void TUndoHandler::UndoCommand(TCommand* command)
  854. {
  855.     FailInfo fi;
  856.     Try(fi)
  857.     {
  858.         command->PrepareForUndoRedo();
  859.         command->UndoIt();
  860.         command->FinishUndoRedo();
  861.         command->RevealUndoRedo();
  862.         fi.Success();
  863.     }
  864.     else // Recover
  865.     {
  866.         command->SetValidationError(fi.error);
  867.         short aCommandNumber = (short)command->fIdentifier;
  868.         //command = CommitACommand(command);
  869.  
  870.         FailNewMessage(fi.error, fi.message, BuildMessage(aCommandNumber, messageCommandError));
  871.     }
  872. }
  873.  
  874. //----------------------------------------------------------------------------------------
  875. // TUndoHandler::RedoAction:
  876. //----------------------------------------------------------------------------------------
  877. #pragma segment MASelCommand
  878.  
  879. EActionType TUndoHandler::RedoAction()
  880. {
  881.     TUndoAction* action = fRedoStack->Top();
  882.     FailNonObject(action);
  883.  
  884.     EActionType actionType = action->fActionType;
  885.  
  886.     TCommand* command = action->fCommand;
  887.     if (command && !command->fCommandDone && command->CanBeUndone() &&
  888.         (command->fValidationError == noErr))
  889.         RedoCommand(command);
  890.  
  891.     fUndoStack->PushAction(fRedoStack->PopAction());
  892.     
  893.     return actionType;
  894. }
  895.  
  896. //----------------------------------------------------------------------------------------
  897. // TUndoHandler::RedoCommand:
  898. //----------------------------------------------------------------------------------------
  899. #pragma segment MASelCommand
  900.  
  901. void TUndoHandler::RedoCommand(TCommand* command)
  902. {
  903.     FailInfo fi;
  904.     Try(fi)
  905.     {
  906.         command->PrepareForUndoRedo();
  907.         command->RedoIt();
  908.         command->FinishUndoRedo();
  909.         command->RevealUndoRedo();
  910.         fi.Success();
  911.     }
  912.     else // Recover
  913.     {
  914.         command->SetValidationError(fi.error);
  915.         short aCommandNumber = (short)command->fIdentifier;
  916.         //command = CommitACommand(command);
  917.  
  918.         FailNewMessage(fi.error, fi.message, BuildMessage(aCommandNumber, messageCommandError));
  919.     }
  920. }
  921.  
  922. //========================================================================================
  923. // CLASS TUndoRedoCommand
  924. //========================================================================================
  925. #undef Inherited
  926. #define Inherited TCommand
  927.  
  928. #pragma segment ClassDescRes
  929. MA_DEFINE_CLASS_M1(TUndoRedoCommand, Inherited);
  930.  
  931. //----------------------------------------------------------------------------------------
  932. // TUndoRedoCommand::TUndoRedoCommand: Empty constructor to satisfy the compiler.
  933. //----------------------------------------------------------------------------------------
  934. #pragma segment MAApplicationRes
  935.  
  936. TUndoRedoCommand::TUndoRedoCommand()
  937. {
  938. }
  939.  
  940. //----------------------------------------------------------------------------------------
  941. // TUndoRedoCommand destructor
  942. //----------------------------------------------------------------------------------------
  943. #pragma segment MADestructorRes
  944.  
  945. TUndoRedoCommand::~TUndoRedoCommand()
  946. {
  947. }
  948.  
  949. //----------------------------------------------------------------------------------------
  950. // TUndoRedoCommand::IUndoRedoCommand:
  951. //----------------------------------------------------------------------------------------
  952. #pragma segment MAInit
  953.  
  954. void TUndoRedoCommand::IUndoRedoCommand(CommandNumber itsCommandNumber)
  955. {
  956.     this->ICommand(itsCommandNumber, gDispatcher, kCantUndo, kDoesNotCauseChange, NULL);
  957. }
  958.  
  959. //----------------------------------------------------------------------------------------
  960. // TUndoRedoCommand::MakeAppleEvent: 
  961. //----------------------------------------------------------------------------------------
  962. #pragma segment MAScriptingRes
  963.  
  964. TAppleEvent* TUndoRedoCommand::MakeAppleEvent()
  965. {
  966.     TAppleEvent* theEvent = new TAppleEvent;
  967.     theEvent->IAppleEvent(kAEMiscStandards, fAEEventID, gServerAddress, kAEWaitReply);
  968.     CTempDesc targetDesc;
  969.     gDispatcher->MakeObjectSpecifier(targetDesc, gDispatcher->GetSpecifierForm());
  970.     theEvent->WriteParameter(keyDirectObject, targetDesc);
  971.     return theEvent;
  972. }
  973.  
  974.  
  975. //========================================================================================
  976. // CLASS TUndoCommand
  977. //========================================================================================
  978. #undef Inherited
  979. #define Inherited TUndoRedoCommand
  980.  
  981. #pragma segment ClassDescRes
  982. MA_DEFINE_CLASS_M1(TUndoCommand, Inherited);
  983.  
  984. //----------------------------------------------------------------------------------------
  985. // TUndoCommand::TUndoCommand: Empty constructor to satisfy the compiler.
  986. //----------------------------------------------------------------------------------------
  987. #pragma segment MAApplicationRes
  988.  
  989. TUndoCommand::TUndoCommand()
  990. {
  991. }
  992.  
  993. //----------------------------------------------------------------------------------------
  994. // TUndoCommand destructor
  995. //----------------------------------------------------------------------------------------
  996. #pragma segment MADestructorRes
  997.  
  998. TUndoCommand::~TUndoCommand()
  999. {
  1000. }
  1001.  
  1002. //----------------------------------------------------------------------------------------
  1003. // TUndoCommand::IUndoCommand:
  1004. //----------------------------------------------------------------------------------------
  1005. #pragma segment MAInit
  1006.  
  1007. void TUndoCommand::IUndoCommand(CommandNumber itsCommandNumber)
  1008. {
  1009.     this->IUndoRedoCommand(itsCommandNumber);
  1010.     fAEEventID = kAEUndo;
  1011. }
  1012.  
  1013. //----------------------------------------------------------------------------------------
  1014. // TUndoCommand::DoIt:
  1015. //----------------------------------------------------------------------------------------
  1016. #pragma segment MAApplicationRes
  1017.  
  1018. void TUndoCommand::DoIt()
  1019. {
  1020.     TUndoHandler::fgUndoHandler->Undo();
  1021. }
  1022.     
  1023. //========================================================================================
  1024. // CLASS TRedoCommand
  1025. //========================================================================================
  1026. #undef Inherited
  1027. #define Inherited TUndoRedoCommand
  1028.  
  1029. #pragma segment ClassDescRes
  1030. MA_DEFINE_CLASS_M1(TRedoCommand, Inherited);
  1031.  
  1032. //----------------------------------------------------------------------------------------
  1033. // TRedoCommand::TRedoCommand: Empty constructor to satisfy the compiler.
  1034. //----------------------------------------------------------------------------------------
  1035. #pragma segment MAApplicationRes
  1036.  
  1037. TRedoCommand::TRedoCommand()
  1038. {
  1039. }
  1040.  
  1041. //----------------------------------------------------------------------------------------
  1042. // TRedoCommand destructor
  1043. //----------------------------------------------------------------------------------------
  1044. #pragma segment MADestructorRes
  1045.  
  1046. TRedoCommand::~TRedoCommand()
  1047. {
  1048. }
  1049.  
  1050. //----------------------------------------------------------------------------------------
  1051. // TRedoCommand::IRedoCommand:
  1052. //----------------------------------------------------------------------------------------
  1053. #pragma segment MAInit
  1054.  
  1055. void TRedoCommand::IRedoCommand(CommandNumber itsCommandNumber)
  1056. {
  1057.     this->IUndoRedoCommand(itsCommandNumber);
  1058.     fAEEventID = kAERedo;
  1059. }
  1060.  
  1061. //----------------------------------------------------------------------------------------
  1062. // TRedoCommand::DoIt:
  1063. //----------------------------------------------------------------------------------------
  1064. #pragma segment MAApplicationRes
  1065.  
  1066. void TRedoCommand::DoIt()
  1067. {
  1068.     TUndoHandler::fgUndoHandler->Redo();
  1069. }
  1070.     
  1071.  
  1072. //========================================================================================
  1073. // CLASS CUndoStackHook
  1074. //========================================================================================
  1075. #undef Inherited
  1076.  
  1077. //----------------------------------------------------------------------------------------
  1078. // CUndoStackHook::Purge:
  1079. //----------------------------------------------------------------------------------------
  1080. #pragma segment MAMemoryRes
  1081.  
  1082. Size CUndoStackHook::Purge(Size needed)
  1083. {
  1084.     // Make memory available by unloading the undo stack. Returns 
  1085.     // the actual amount of memory purged. 
  1086.  
  1087.     return TUndoHandler::fgUndoHandler->Purge(needed);
  1088. }
  1089.  
  1090. //----------------------------------------------------------------------------------------
  1091. // End of UUndo.cp
  1092.  
  1093. #pragma segment Inline
  1094.